module ActiveBackground
  module Handler
    class Job < ActiveBackground::Handler::Base
  
      # initialize implementation by including the default worker directories
      def initialize
        super
        
        @job_dirs = @config.job.dirs
        @job_files = Hash.new
        
        @config.job.dirs.each do |dir|
          Dir.foreach(dir) do |file|
            unless ['.', '..', '.svn'].include?(file)
              begin
                load dir + file
              end
            end
          end
        end
      end
      
      # retrieves the worker from one of the registered directories
      # and passes it on to the server.
      # 
      # Arguments:
      #     <tt>worker</tt>: Name of worker can be passed, unless
      #     options[:class], name is converted to class name.
      #     <tt>options</tt>: Hash of options allow you to specify worker creation parameters.
      #     <tt>argv</tt>: Hash of argv are passed on to the worker (without modification).
      #     
      # Options:
      # 
      #     <tt>:class</tt>: Name of worker passed as a symbol
      #     <tt>:key</tt>: Uniq key that is assigned to the worker (uniq key is
      #     genenerated if no :key is passed)
      def create(job, options={}, *argv, &job_block)

        klass = options[:class] || job
        # convert class name (symbol) to constant and initialize
        begin
          job = get_job_class(klass).new(job, options, argv)
          job.define_job(&job_block) if block_given?
        rescue
          if block_given?
            job = ActiveBackground::Job.new
            job.define_job(&job_block)
          else
            raise "Job: Job does not exist, please make sure you have registered the directory that contains the job"
          end
        end
  
        # try to pass a job to the server thru MiddleMan
        begin
          # pass the initialized worker to the server
          add(job)
          # return the worker (job) key. This allows to fetch the worker when needed.
          return job.key
        rescue Exception => e # something went wrong while creating the worker
          debug = e.to_s + "\n" + e.backtrace.join("\n")
          @logger.warn(
            "job: Cannot create job\n" +
            debug || ""
          )
          raise "Job: Something went wrong while creating a job, please check if your configuration is correct and your server is alive"
        end
      end
      
      # 
      # Arguments:
      #   <tt>options</tt>: 
      # 
      # Options:
      #   <tt>:status</tt>: status or array of statusses that need to be count
      #   
      def count(options=[])
        begin
          count = @middle_man.server.count(:all, options)
          return count if count
          return 0
        rescue Exception => e
          count(options)
        end
      end
            
      # add job with a uniq key
      def add(job)
        @middle_man.server.add(job)
      end
      
      def terminate(key)
        @middle_man.server.send_command_to_job(key, :terminate)
      end

      private
        # retrieves the constant of the worker name
        # based on a symbol that is passed on. The
        # following code passes back FileRetriever
        # constant so you can initialize it.
        # 
        #   klass = get_worker_class(:file_retriever)
        #   @worker = klass.new
        # 
        # Arguments:
        #     <tt>klass:</tt> Class name passed as a symbol
        # 
        # returns constant converted from a symbol
        def get_job_class(klass)
          # convert the symbol to a string and split it
          # to an Array and join them together by
          # capitalizing the parts of the Array.
          return Object.const_get(klass.to_s.split('_').inject('') {|klass_name, slice| klass_name  << slice.capitalize})
        end
    end
  end
end